<?php

/**
 * Library :: Widget :: Recordset
 *
 * Warlock is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 *
 * @package    warlock
 * @author     David Cole <neophyte@sourcetutor.com>
 * @license    GNU/GPL v2
 */

using('Library.Widgets.Form.*');

class Form extends Object
{
    var $_Name;
    var $_Action;
    var $_Method;
    var $_EncType;

    var $_FieldTypes = array();
    var $_Fields     = array();
    var $_FieldSet   = array();
    var $_Actions    = array();
    
    /**#@+
     * Required Core Objects
     *
     * These are references to the core objects required by this
     * class.
     *
     * @access private
     * @var    object
     */
    var $_Model;
    var $_Error;
    var $_Profiler;
    /**#@-*/

    function __construct($name = '', $action, $method = 'POST', $enctype = 'application/x-www-form-urlencoded')
    {
        // Get References to required objects
        $this->_Error    = &Vault::Get('Debug_Error');
        $this->_Profiler = &Vault::Get('Debug_Profiling');
        $this->_Model    = &Vault::Get('Model');

        // Set form properties
        $this->_Name    = $name;
        $this->_Action  = $action;
        $this->_Method  = $method;
        $this->_EncType = $enctype;
    }

    Function AddFieldSet($title, $description = '')
    {
        $this->_Fields[] = array('title' => $title, 'description' => $description, 'fields' => array());
        $this->_FieldSet = &$this->_Fields[count($this->_Fields) - 1]['fields'];
    }
    
    function Submitted()
    {
	    if (($_SERVER['REQUEST_METHOD'] == strtoupper($this->_Method)) && isset($_POST[$this->_Name]))
	       return true;
	    else
	       return false;
    }

    function SetEncType($enctype)
    {
        $this->_EncType = $enctype;
    }
    
    function Validate()
    {
        $error = false;
        
        for ($i = 0, $imax = count($this->_Fields); $i < $imax; $i++)
            for ($x = 0, $xmax = count($this->_Fields[$i]['fields']); $x < $xmax; $x++)
                if (!$this->_Fields[$i]['fields'][$x]->Validate())
                    $error = true;
    
        return $error ? false : true;
    }

    function AddAction($name, $title, $callback, $validate = true)
    {
        $this->_Actions[] = array('name'     => $name,
                                  'title'    => $title,
                                  'callback' => $callback,
                                  'validate' => $validate);
    }
    
    function Add(&$field)
    {
        if (count($this->_Fields) == 0)
            $this->AddFieldSet('Default');
                    
        $this->_FieldSet[]   = &$field;
        $this->_FieldTypes[] = $field->Type;
    }

    function Process()
    {

        if ($this->Submitted())
        {                                   
            /*
             * Form has been submitted lets try and find an action to perform
             * with the submitted data
             */
                
            for ($i = 0, $imax = count($this->_Actions); $i < $imax; $i++)
            {
                if (($this->_Actions[$i]['name'] == $_POST[$this->_Name]) && is_callable($this->_Actions[$i]['callback']))
                {
                    
                    if ($this->_Actions[$i]['validate'])
                    {
                        // Validate the form field data before calling the action
                        if ($this->Validate())
                        {
                            call_user_func($this->_Actions[$i]['callback']);
                            return true;                            
                        }
                        else 
                        {
                            // Validation failed
                            $this->_Model->Set('Page.Messages.Error', array('Required form field data missing or invalid.'));
                            $this->_Model->Body('library', $this->ToArray(), $this->_Name, 'form');
                            return true;                            
                        }
                    }
                    else 
                    {         
                        // No form field validation required           
                        call_user_func($this->_Actions[$i]['callback']);
                        return true;
                    }
                }
            }
                
            // No action?
            $this->_Error->Log('Widget[Form] :: Error locating action to process form data.');
            return false;           
        }
        else
        {
            /*
             * Form has yet to be submitted or contains invalid data in either
             * case add the form to the page model to be displayed.
             */
            
            $this->_Model->Body('library', $this->ToArray(), $this->_Name, 'form');
            return true;
        }
    }
    
    function ToArray()
    {
        $return = array();      
        
        // Form Properties
        $return['form'] = array('name'    => $this->_Name,
                                'action'  => $this->_Action,
                                'method'  => $this->_Method,
                                'enctype' => $this->_EncType);

        // Field Types
        $return['fieldtypes'] = array_unique($this->_FieldTypes);
                                
        // Form Actions
        for ($i = 0, $imax = count($this->_Actions); $i < $imax; $i++)
            $return['actions'][] = array('name'  => $this->_Actions[$i]['name'],
                                         'title' => $this->_Actions[$i]['title']);
               
        // Form Fields
        for ($i = 0, $imax = count($this->_Fields); $i < $imax; $i++)
        {
            $temp = array();
            
            $temp['title']       = $this->_Fields[$i]['title'];
            $temp['description'] = $this->_Fields[$i]['description'];
            
            for ($x = 0, $xmax = count($this->_Fields[$i]['fields']); $x < $xmax; $x++)
                $temp['fields'][] = $this->_Fields[$i]['fields'][$x]->ToArray();
                
            $return['fieldsets'][] = $temp;
        }

        return $return;
    }
}

?>